Shared memory [system call]

공유 메모리(Shared memory) <sys/shm.h>
Kernel space에 메모리 공간을 생성하고, 해당 공간을 변수처럼 사용
message queue처럼 FIFO 이 아닌, 해당 메모리 주소를 변수처럼 접근해서 사용할 수 있다.
공유 메모리 key를 가지고, 여러 프로세스 접근 가능
공유 메모리 생성
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
//ex)
shmid=shmget((key_t)1234, SIZE, IPC_CREAT|0666)
size: 공유 메모리 크기
shmflg: 공유 메모리 속성
return value: 공유 메모리 식별자
공유 메모리 연결
#include <sys/types.h>
#include <sys/shm.h>
void* shmat(int shmid, const void* shmaddr, int shmflg);
//ex)
shmaddr=(char*)shmat(shmid, (char*)NULL, 0);
shmid: shmget함수로 생성한 공유 메모리 식별자
shmaddr: 공유 메모리 연결 주소 - (char*)NULL로 지정시 적당한 주소로 연결
shmflg: 공유 메모리 읽기/쓰기 권한(0이면 읽기/쓰기 가능, SHM_RDONLY면 읽기만 가능)
return value: 성공시 연결된 공유 메모리의 시작 주소를 리턴
공유 메모리 연결 해제(메모리가 삭제되지는 않는다.)
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(char* shmaddr);
공유 메모리에서 읽기
printf("%s\n", (char*)shmaddr);
공유 메모리에 쓰기
strcpy((char*)shmaddr, "LINUX Programming");
공유 메모리 컨트롤(메모리 삭제)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds* buf);
//ex)
shmctl(shmid, IPC_RMID, (struct shmid_ds*)NULL);
shmid: shmget 함수로 생성된 공유 메모리 식별자
cmd: 수행할 제어 기능(IPC_RMID -shmid로 지정된 공유 메모리 제거
buf: 제어 기능에 사용되는 공유 메모리 구조체의 구조
sharedmemory.c
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
int shmid, pid;
char* shmaddr_parent, *shmaddr_child;
shmid=shmget((key_t)1234, 10, IPC_CREAT|0644);
if(shmid==-1){
perror("shmget error\n");
exit(1);
}
pid=fork();
if(pid>0){ //parent
wait(0);
shmaddr_parent=(char*)shmat(shmid, (char*)NULL, 0);
printf("%s\n", shmaddr_parent);
shmdt((char*)shmaddr_parent);
printf("user place pid addr: %p\n", &pid);
printf("parent print:%p\n", (char*)shmaddr_parent); //
printf("parent PID: %d, child(parent) PID: %d\n", getpid(), pid);
}else{ //child
shmaddr_child=(char*)shmat(shmid, (char*)NULL, 0);
strcpy((char*)shmaddr_child, "\nHello Parent!\n");
shmdt((char*)shmaddr_child);
printf("child print:%p\n", (char*)shmaddr_child);
printf("child(child) PID: %d\n", getpid());
exit(0);
}
shmctl(shmid, IPC_RMID, (struct shmid_ds*)NULL);
return 0;
}

child print:0x7f405bf86000

child(child) PID: 1898


Hello Parent!


user place pid addr: 0x7fff8cdf1eb0

parent print:0x7f405bf86000

parent PID: 1897, child(parent) PID: 1898

위와 같이 공유 메모리는 실제로 커널 내에 있는 메모리 공간을 돌려주지는 않는다.
커널에게 시스템콜로 공유 메모리를 요청하면, 커널이 가상메모리 상에서 유저 메모리 공간을 할당해주는 듯 하다.
유저 메모리 공간의 주소와 실제 물리메모리에서 동일한 공간을 포인팅?(일단 가상 메모리 상에서 물리 메모리 상에서 같은 주소를 가짐)
(아니면 주소만 그렇게 설정이 되던지..) 확인해볼것!!